// Package event is a package to process mqtt event
package event

import (
	"fmt"
	"gitee.com/wangqiOvO/mapper-go-sdk/internal/clients"
	"gitee.com/wangqiOvO/mapper-go-sdk/internal/common"
	"gitee.com/wangqiOvO/mapper-go-sdk/internal/configmap"
	"gitee.com/wangqiOvO/mapper-go-sdk/internal/controller"
	"gitee.com/wangqiOvO/mapper-go-sdk/internal/di"
	"gitee.com/wangqiOvO/mapper-go-sdk/pkg/models"
	"k8s.io/klog/v2"
	"sync"
	"time"
)

// InitTwin initialize the timer to get twin value.
func InitTwin(instances map[string]*configmap.DeviceInstance,drivers models.ProtocolDriver,mqttClient clients.MqttClient,wg *sync.WaitGroup,dic *di.Container,mutex *sync.Mutex) error{
	klog.V(4).Info("InitTwin start")
	for k,v := range instances{
		for _,twinV := range v.Twins{
			// ---------------setVisitor---------------
			err := controller.SetVisitor(k, twinV, drivers, mutex, dic)
			if err != nil {
				klog.V(4).Info("setVisitor error",err.Error())
				klog.Error(err)
				return err
			}
			// ---------------setVisitor---------------
			// ---------------Send Data by MQTT---------------
			collectCycle := time.Duration(twinV.PVisitor.CollectCycle)
			// If the collect cycle is not set, set it to 1 second.
			if collectCycle == 0 {
				collectCycle = 1 * time.Second
			}
			twinData := TwinData{
				Name: twinV.PropertyName,
				Type: twinV.Desired.Metadatas.Type,
				Topic: fmt.Sprintf(common.TopicTwinUpdate,k),
				MqttClient: mqttClient,
				driverUnit: DriverUnit{
					instanceID: k,
					twin: twinV,
					drivers: drivers,
					mutex: mutex,
					dic: dic,
				},
			}
			timer := common.Timer{Function: twinData.Run, Duration: collectCycle, Times: 0}
			wg.Add(1)
			go func() {
				defer wg.Done()
				timer.Start()
			}()
			// ---------------Send Data by MQTT---------------

		}
	}
	return nil
}

// InitData initialize the timer to get data.
func InitData(instances map[string]*configmap.DeviceInstance,drivers models.ProtocolDriver,mqttClient clients.MqttClient,wg *sync.WaitGroup,dic *di.Container,mutex *sync.Mutex) error{
	klog.V(4).Info("InitData start")
	for k,v := range instances{
		for _,twinV := range v.Twins{
			// ---------------Send Data by MQTT---------------
			collectCycle := time.Duration(twinV.PVisitor.CollectCycle)
			// If the collect cycle is not set, set it to 1 second.
			if collectCycle == 0 {
				collectCycle = 1 * time.Second
			}
			twinData := TwinData{
				Name: twinV.PropertyName,
				Type: twinV.Desired.Metadatas.Type,
				Topic: fmt.Sprintf(common.TopicDataUpdate,k),
				MqttClient: mqttClient,
				driverUnit: DriverUnit{
					instanceID: k,
					twin: twinV,
					drivers: drivers,
					mutex: mutex,
					dic: dic,
				},
			}
			timer := common.Timer{Function: twinData.Run, Duration: collectCycle, Times: 0}
			wg.Add(1)
			go func() {
				defer wg.Done()
				timer.Start()
			}()
			// ---------------Send Data by MQTT---------------

		}
	}
	return nil
}

// InitGetStatus start timer to get device status and send to eventbus.
func InitGetStatus(instances map[string]*configmap.DeviceInstance,drivers models.ProtocolDriver,mqttClient clients.MqttClient,wg *sync.WaitGroup,dic *di.Container,mutex *sync.Mutex) error {
	for k,v := range instances{
		var statusData StatusData
		var collectCycle time.Duration
		for _,twinV := range v.Twins{
			// ---------------Send Data by MQTT---------------
			collectCycle = time.Duration(twinV.PVisitor.CollectCycle)
			// If the collect cycle is not set, set it to 1 second.
			if collectCycle == 0 {
				collectCycle = 1 * time.Second
			}
			statusData = StatusData{
				topic: fmt.Sprintf(common.TopicStateUpdate,k),
				MqttClient: mqttClient,
				driverUnit: DriverUnit{
					instanceID: k,
					twin: twinV,
					drivers: drivers,
					mutex: mutex,
					dic: dic,
				},
			}
		}
		timer := common.Timer{Function: statusData.Run, Duration: collectCycle, Times: 0}
		wg.Add(1)
		go func() {
			defer wg.Done()
			timer.Start()
		}()
	}
	return nil
}



